package com.cy.store.controller;

import com.cy.store.controller.ex.*;
import com.cy.store.entity.User;
import com.cy.store.service.IUserService;
import com.cy.store.service.ex.InsertException;
import com.cy.store.service.ex.UsernameDuplicatedException;
import com.cy.store.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping("/users")
public class UserController extends BaseController {

    @Autowired
    private IUserService userService;

//    @Autowired
//    private HttpSession session;

    /**
     * 1.接受数据方式：请求数据方法设置为pojo类型来接受前端的数据
     * SpringBoot会将前端的url地址中的参数名和pojo中的属性名进行比较
     * 如果属性名相同，则将注入到pojo的属性中
     *
     * @param user
     * @return
     */
    @PostMapping("/reg")
    public JsonResult<Void> reg(User user) {
        //创建结果响应对象
        userService.reg(user);
        return new JsonResult<>(OK);
    }

    /**
     * 2.接收数据方式：当请处理方法的参数列表设置为非pojo类型，
     * SpringBoot直接将请求的参数名和方法的参数名直接进行比较，
     * 如果名称相同如果名称相同自动完成注入
     *
     * @param username
     * @param password
     * @return
     */
    @PostMapping("/login")
    public JsonResult<User> login(String username, String password, HttpSession session) {
        User user = userService.login(username, password);

        //将用户的信息保存到session中
        session.setAttribute("uid", user.getUid());
        session.setAttribute("username", user.getUsername());

        System.out.println(getUidFromSession(session));
        System.out.println(getUsernameFromSession(session));

        return new JsonResult<User>(OK, user);
    }

    /**
     * 修改密码
     *
     * @param oldPassword
     * @param newPassword
     * @return
     */
    @PutMapping("/change_password")
    public JsonResult<Void> changePassword(String oldPassword, String newPassword, HttpSession session) {
        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);
        userService.changePassword(uid, username, oldPassword, newPassword);
        //移出用户信息
        session.removeAttribute("uid");
        session.removeAttribute("username");
        return new JsonResult<>(OK);
    }

    /**
     * 回显用户数据
     *
     * @param session
     * @return
     */
    @RequestMapping("/get_by_uid")
    public JsonResult<User> getByUid(HttpSession session) {
        User user = userService.getByUid(getUidFromSession(session));
        return new JsonResult<>(OK, user);
    }

    /**
     * 修改用户信息
     *
     * @return
     */
    @RequestMapping("/change_info")
    public JsonResult<Void> changeInfo(User user, HttpSession session) {
        //user对象中有四部分数据：username,phone,email,gender
        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);
        userService.changeInfo(uid, username, user);
        return new JsonResult<>(OK);
    }

    //设置上传头像的最大值
    public static final Integer AVATAR_MAX__SIZE = 10 * 1024 * 1024;

    //设置文件上传保存地址
    @Value("${store.path}")
    private String path;
    //限制上传文件的类型
    public static final List<String> AVATAR_TYPE = new ArrayList<>();

    static {
        AVATAR_TYPE.add("image/jpeg");
        AVATAR_TYPE.add("image/png");
        AVATAR_TYPE.add("image/bmp");
        AVATAR_TYPE.add("image/gif");

    }


    /**
     * 更改用户头像
     * MultipartFile接口时springMVC提供的接口，这个接口包装了获取文件的数据（任何文件）
     * springBoot整合了springMVC
     * 只需要在处理请求参数列表上声明一个参数类型为MultipartFile的参数，然后springBoot会自动将传递给服务的文件数据赋值给这个参数
     *
     * @param session
     * @param file
     * @return
     */
    @RequestMapping("/change_avatar")
    public JsonResult<String> changeAvatar(HttpSession session, @RequestParam("file") MultipartFile file) {
        //判断文件是否为空
        if (file.isEmpty()) {
            throw new FileEmptyException("文件为空，请重新上传");
        }

        //判断文件大小是否符合要求
        if (file.getSize() > AVATAR_MAX__SIZE) {
            throw new FileSizeException("文件大于10MB，请重新选择");
        }

        //判断文件类型
        String type = file.getContentType();
        //如果集合包含谋和集合元素返回true
        if (!AVATAR_TYPE.contains(type)) {
            throw new FileTypeException("文件类型不支持");
        }


        //file对象指向这个路径（本体地址），file是否存在
        File dir = new File(path);
        if (!dir.exists()) {//如果不存在
            dir.mkdirs();//创建当前的目录
        }

        //获取文件名称，UUID工具来生成一个新的字符串作为文件名
        String originalFilename = file.getOriginalFilename();//例如avatar01.png

        //通过截取最后一个“.”来获取文件类型的字符串
        int index = originalFilename.lastIndexOf(".");
        String suffix = originalFilename.substring(index);
        String filename = UUID.randomUUID().toString().toUpperCase() + suffix;

        File dest = new File(path, filename);//是一个空文件 其中上一个File对象是创建包结构 这个file对象是图片对象
        // (将图片保存到本地，但保存到数据库中的地址为网络地址)
        //参数file中的数据写道这个文件中
        try {
            file.transferTo(dest);//将file文件中的数据写到dest文件中
        } catch (FileStateException e) {
            throw new FileUploadException("文件状态异常");
        } catch (IOException e) {
            System.out.println(e.getMessage());
            throw new FileUploadException("文件读写异常");
        }
        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);
        //将访问路径配置到avatar中
        String avatar = "../upload/" + filename;
        userService.changeAvatar(uid, avatar, username);
        //返回用户的头像路径给前端，将来用于展示使用
        return new JsonResult<>(OK, avatar);
    }


}
